#!/usr/bin/env python
# encoding: utf-8
"""
@file: zhouqi.py
@time: 2016/11/1 上午11:16
"""
# 三角函数周期问题
# 通过化简得得到：Asin(wx+Q)+h,Acos(wx+q)+h,Atan(Wx+q)+h的形式，然后利用公式求解
from mathsolver.functions.base import *
from sympy import pi, Abs, sympify, simplify
from sympy.core.numbers import Pi
from sympy.core.mul import Mul
from mathsolver.functions.sanjiao import hanshu as hu
from mathsolver.functions.budengshi import common_opers as co
from mathsolver.functions.sanjiao.jieti import SanJiaoHanShu003
from itertools import chain
from mathsolver.functions.sanjiao.huajian import trig_simplify


# 带绝对值的三角函数周期问题
class ZhouQi001(BaseFunction):
    @staticmethod
    def try_cycle(f, has_pi=True):
        f = sympify(f)
        x_symbol = list(f.free_symbols)[0]
        cycles1 = [pi / i for i in range(2, 11)]
        cycles2 = [pi * i for i in range(1, 11)]
        cycles3 = [sympify('1') / i for i in range(2, 11)]
        cycles4 = [sympify(str(i)) for i in range(1, 11)]
        if has_pi:
            cycles = chain(cycles3, cycles4)
        else:
            cycles = chain(cycles1, cycles2)
        tmp_fs = map(lambda t_c: (t_c, simplify(f.subs(x_symbol, x_symbol + t_c))), cycles)
        same_fs = list(filter(lambda t: t[1] == f, tmp_fs))
        if same_fs:
            return same_fs[0][0]
        else:
            return None

    def solver(self, *args):
        self.label.add('三角函数最小正周期')
        if isinstance(args[0], BaseSinFunc):
            f = sympify(args[0].expression)
        elif isinstance(args[0], BaseEq):
            f = args[0].sympify()[1]
        else:
            f = sympify(args[0])
        if isinstance(f, Abs) or isinstance(f, Mul):  # 函数f(x)=|sin(x+\\frac{π}{3})|的最小正周期是().
            arg_f = f.args[0] if len(f.args) == 1 else f.args[1].args[0]
            sim_arg_f = trig_simplify(arg_f)
            self.steps.append(['对于y = %s' % new_latex(arg_f), ''])
            self.steps.append(['化简:', ':'])
            self.steps.append(['= ' + new_latex(sim_arg_f), ''])
            new_f = abs(sim_arg_f)
            _, const = co.split_mons_const(sim_arg_f)
            self.steps.append(['函数y = %s' % new_latex(new_f),
                               '是y = %s函数轴上方的图象不动将x轴下方的图象向上对折得到的.' % new_latex(sim_arg_f)])
            if not const:  # 如果没有有常数
                t_c = hu.trig_cycle(sim_arg_f) / 2
                self.steps.append(['故T\' = \\frac{T}{2} = ', new_latex(t_c)])
                self.output.append(BaseNumber(t_c))
            else:
                t_c = hu.trig_cycle(sim_arg_f)
                self.steps.append(['故T\' = T = ', new_latex(t_c)])
                self.output.append(BaseNumber(t_c))
            return self
        elif isinstance(f, Add):  # 函数f(x)=|sin\\frac{π}{2}x|+|cos\\frac{π}{2}x|的最小正周期是().
            x_symbol = list(f.free_symbols)[0]
            abs_mos = co.absed_mo_v2(f)
            p = r'Abs\(.*\)'
            has_pi = False
            for m in abs_mos:
                tmp = sympify(re.findall(p, m)[0])
                trig_arg = tmp.args[0]
                arg = trig_arg.args[0]
                coef = arg.coeff(x_symbol)
                if isinstance(coef, Pi) or pi in coef.args:
                    has_pi = True
                    break
            t_c = ZhouQi001.try_cycle(f, has_pi)
            self.steps.append(['\because f(x + %s) = ' % new_latex(t_c),
                               new_latex(f.subs(x_symbol, x_symbol + t_c)) + '=%s' % new_latex(f) + '=f(x)'])
            self.steps.append(['\therefore 函数f(x)的最小正周期为 ', new_latex(t_c)])
            self.output.append(BaseNumber(t_c))
        else:
            raise Exception('Type Match Error')
        return self


# 使用Mathematica解决
class ZhouQi002(BaseFunction):
    def solver(self, *args):
        return self


# 周期问题
class ZhouQi(BaseFunction):
    CLS = [SanJiaoHanShu003, ZhouQi001]

    def solver(self, *args):
        solve_result = None
        for cl in ZhouQi.CLS:
            try:
                solve_result = cl(verbose=True)
                solve_result.known = self.known
                solve_result = solve_result.solver(*args)
                solve_result.label.add('三角函数周期')
                break
            except Exception:
                solve_result = None
        if not solve_result:
            raise Exception('Can not solve the symmetry axis')
        return solve_result


if __name__ == '__main__':
    pass
